package com.xbongbong.saas.analytical.impl;

import com.alibaba.fastjson.JSONObject;
import com.xbongbong.paas.constant.TimeConstant;
import com.xbongbong.paas.pojo.dto.ValidateDataDTO;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.paas.toolbox.util.DateUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.WorkReportErrorCodeEnum;
import com.xbongbong.saas.analytical.SaasValidateAnalyticalService;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.domain.entity.WorkReportSetEntity;
import com.xbongbong.saas.enums.DeadlineTimeEnum;
import com.xbongbong.saas.enums.WorkReportDeadDayTypeEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.WorkReportFieldEnum;
import com.xbongbong.saas.enums.business.WorkReportTypeEnum;
import com.xbongbong.saas.help.SaasDataInitHelp;
import com.xbongbong.saas.model.WorkReportSetModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * @author 吴峰
 * @date 2021/07/15 17:15
 */
@Service("workReportAnalyticalServiceImpl")
public class WorkReportValidateAnalyticalServiceImpl implements SaasValidateAnalyticalService {
    private static final Logger LOGGER = LoggerFactory.getLogger(WorkReportValidateAnalyticalServiceImpl.class);

    @Resource
    private WorkReportSetModel workReportSetModel;

    @Override
    public List<Integer> type() {
        return Arrays.asList(XbbRefTypeEnum.WORKREPORT_DAILY.getCode(), XbbRefTypeEnum.WORKREPORT_MONTHLY.getCode(), XbbRefTypeEnum.WORKREPORT_WEEKLY.getCode(),
                XbbRefTypeEnum.WORK_REPORT.getCode());
    }

    @Override
    public void analyticalData(ValidateDataDTO validateDataDTO) throws XbbException {
        beforeSave(validateDataDTO);
    }
    
    public void beforeSave(ValidateDataDTO validateDataDTO) throws XbbException {
       try {
           JSONObject data = validateDataDTO.getData();

           Integer reportType = data.getInteger(WorkReportFieldEnum.TYPE.getAttr());
           Long reportDate = StringUtil.StringToLong(data.getString(WorkReportFieldEnum.REPORT_DATE.getAttr()), null);
           if (Objects.isNull(reportDate)) {
               throw new XbbException(WorkReportErrorCodeEnum.API_ERROR_207017);
           }
           // 新建时设置工作报告的补发状态
           if (Objects.isNull(validateDataDTO.getDataId()) || Objects.equals(validateDataDTO.getDataId(), 0L) || Objects.equals(BasicConstant.ZERO_LONG, validateDataDTO.getDataId())) {
               Boolean isRessue = isReissue(validateDataDTO.getCorpid(), reportType, reportDate);
               if(isRessue != null) {
                   data.put(WorkReportFieldEnum.IS_RESSUE.getAttr(), isRessue ? 1 : 0);
               }
           }
           for (Map.Entry<String,Object> entry : SaasDataInitHelp.initWorkReport().entrySet()){
               if (!data.containsKey(entry.getKey())) {
                   SaasDataInitHelp.antDataSet(data,entry.getKey(),entry.getValue());
               }
           }
           validateDataDTO.setData(data);
       } catch (XbbException e) {
           throw e;
       } catch (Exception e) {
           LOGGER.error("WorkReportValidateAnalyticalServiceImpl.beforeSave error", e);
           throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
       }
    }

    /**
     * 是否补发
     * @param corpid 公司id
     * @param type 工作报告类型
     * @param workReportDate 报告时间
     */
    private Boolean isReissue(String corpid, Integer type, Long workReportDate) throws XbbException{
        Long now = DateTimeUtil.getInt();
        WorkReportSetEntity workReportSetEntity = workReportSetModel.getByType(type,corpid);
        if (workReportSetEntity == null) {
            workReportSetEntity = new WorkReportSetEntity();
        }
        Integer reisssue = workReportSetEntity.getReissue();
        reisssue = reisssue == null ? 0 : reisssue;
        Boolean allowReissue = Objects.equals(reisssue,1);
        Integer reissueTimeLimit = workReportSetEntity.getReissueTimeLimit() == null ? 0 : workReportSetEntity.getReissueTimeLimit();
        Integer deadlineOption = workReportSetEntity.getDeadlineOption() == null ? 1 : workReportSetEntity.getDeadlineOption();
        String deadlineTime = workReportSetEntity.getDeadlineTime() == null ? DeadlineTimeEnum.DEADLINE_TIME_TWENTY_FOUR.getName() : workReportSetEntity.getDeadlineTime();
        WorkReportTypeEnum workReportTypeEnum = WorkReportTypeEnum.getByType(type);
        WorkReportDeadDayTypeEnum deadDayTypeEnum = WorkReportDeadDayTypeEnum.getByCodeType(deadlineOption, workReportTypeEnum.getType());

        Long deadline = 0L;
        switch (workReportTypeEnum){
            case DAILY:
                switch (deadDayTypeEnum){
                    case TODAY:
                        //本日
                        deadline = DateTimeUtil.getTodayInt(workReportDate);
                        break;
                    case TOMORROW:
                        //次日
                        deadline = DateTimeUtil.getTodayInt(workReportDate) + TimeConstant.SECONDS_PER_DAY;
                        break;
                    default:
                        break;
                }
                break;
            case WEEKLY:
                switch (deadDayTypeEnum){
                    case FRIDAY:
                        //周五
                        deadline = DateTimeUtil.getWeekMorningInSomeday(workReportDate) + TimeConstant.SECONDS_PER_DAY * 4;
                        break;
                    case SATURDAY:
                        //周六
                        deadline = DateTimeUtil.getWeekMorningInSomeday(workReportDate) + TimeConstant.SECONDS_PER_DAY * 5;
                        break;
                    case SUNDAY:
                        //本日
                        deadline = DateTimeUtil.getWeekMorningInSomeday(workReportDate) + TimeConstant.SECONDS_PER_DAY * 6;
                        break;
                    case MONDAY:
                        //下周一
                        deadline = DateTimeUtil.getWeekMorningInSomeday(workReportDate) + TimeConstant.SECONDS_PER_DAY * 7;
                        break;
                    default:
                        break;
                }
                break;
            case MONTHLY:
                switch (deadDayTypeEnum){
                    case FIRST_DAY_OF_NEXT_MONTH:
                        //次月第一天
                        deadline = DateTimeUtil.getLastDateOfMonthInSomeday(workReportDate);
                        break;
                    case LAST_DAY_OF_MONTH:
                        //当月最后一天
                        deadline = DateTimeUtil.getLastDateOfMonthInSomeday(workReportDate) - TimeConstant.SECONDS_PER_DAY;
                        break;
                    default:
                        break;
                }
                break;
            default:
                break;
        }
//        deadline = deadline + (DeadlineTimeEnum.getDeadlineTimeByName(deadlineTime) == null ? TimeConstant.SECONDS_PER_DAY : DeadlineTimeEnum.getDeadlineTimeByName(deadlineTime).getTimestamp());
        // 提交工作报告的截止时间可以任意设置，所以是否为补发只能如此处理
        String[] hourMinuteList = deadlineTime.split(StringConstant.COLON);
        Integer hour = Integer.valueOf(hourMinuteList[0]);
        Integer minute = Integer.valueOf(hourMinuteList[1]);
        deadline = deadline + hour * TimeConstant.SECONDS_PER_HOUR + minute * TimeConstant.SECONDS_PER_MINUTE;

        boolean isReissue = false;
        boolean isLate = false;
        if(deadline < now) {
            isLate = true;
            isReissue = true;
        }
        if(allowReissue) {
            // 允许补发且超时，只有日报有补发天数限制
            reissueTimeLimit = WorkReportTypeEnum.DAILY == workReportTypeEnum ? reissueTimeLimit : 0;
            long ressueTime = (long)reissueTimeLimit * TimeConstant.SECONDS_PER_DAY;
            if(reissueTimeLimit > 0 && workReportDate < DateUtil.getTodayInt((int)(now - ressueTime))) {
                throw new XbbException(WorkReportErrorCodeEnum.API_ERROR_207012);
            }
        } else {
            // 不允许补发且超时
            if(isLate) {
                throw new XbbException(WorkReportErrorCodeEnum.API_ERROR_207011);
            }
        }

        return  isReissue;
    }
    
}
